package com.alogic.jsoup;

import com.alogic.xscript.Logiclet;
import com.alogic.xscript.LogicletContext;
import com.alogic.xscript.Script;
import com.alogic.xscript.doc.XsObject;
import com.alogic.xscript.doc.json.JsonObject;
import com.anysoft.util.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.HashMap;
import java.util.Map;

/**
 * 缺省实现
 *
 * @since 1.6.13.13 [20200904 duanyy] <br>
 */
public class DefaultWhiteList extends WhiteList.Abstract {

    /**
     * tag的白名单列表
     */
    protected Map<String,Tag> tags = new HashMap<String,Tag>();

    protected final String objectId = "$whitelist";

    @Override
    public Tag getTag(String name) {
        return tags.get(name);
    }

    @Override
    public WhiteList addTags(String...names){
        for (String name:names) {
            if (StringUtils.isNotEmpty(name)) {
                boolean exist = tags.containsKey(name);
                if (!exist) {
                    tags.put(name, new Tag(name));
                }
            }
        }
        return this;
    }

    @Override
    public WhiteList addTagAttrs(String name,String...attrs){
        Tag found = tags.get(name);
        if (found == null){
            found = new Tag(name);
            tags.put(name,found);
        }
        for (String attr:attrs) {
            if (StringUtils.isNotEmpty(attr)) {
                found.addAttr(attr);
            }
        }
        return this;
    }

    @Override
    public WhiteList addTagExtendAttr(String tag, String name, String value) {
        Tag found = tags.get(tag);
        if (found == null){
            found = new Tag(tag);
            tags.put(tag,found);
        }
        found.addExtAttr(name,value);
        return this;
    }

    @Override
    public WhiteList addTagEvent(String name, Logiclet event){
        Tag found = tags.get(name);
        if (found == null){
            found = new Tag(name);
            tags.put(name,found);
        }
        found.setEvent(event);
        return this;
    }

    @Override
    public void configure(Properties p) {

    }

    @Override
    public void configure(Element root, Properties p) {
        XmlElementProperties props = new XmlElementProperties(root,p);
        configure(props);

        Element onLoadElem = XmlTools.getFirstElementByPath(root,"on-load");
        if (onLoadElem != null){
            Logiclet onLoad = Script.create(onLoadElem, props);
            if (onLoad != null){
                LogicletContext logicletContext = new LogicletContext(Settings.get());
                try {
                    logicletContext.setObject(objectId, this);
                    XsObject doc = new JsonObject("root",new HashMap<String,Object>());
                    onLoad.execute(doc,doc, logicletContext, null);
                }catch (Exception ex){
                    LOG.info("Failed to execute onload script:" + ExceptionUtils.getStackTrace(ex));
                }finally{
                    logicletContext.removeObject(objectId);
                }
            }
        }
        NodeList nodeList = XmlTools.getNodeListByPath(root,"on-tag");
        for (int i = 0 ; i < nodeList.getLength() ; i ++){
            Node node = nodeList.item(i);
            if (Node.ELEMENT_NODE != node.getNodeType()){
                continue;
            }
            Element elem = (Element)node;
            String tag = elem.getAttribute("tag");
            if (StringUtils.isNotEmpty(tag)) {
                try {
                    Logiclet event = Script.create(elem, props);
                    if (event != null) {
                        this.addTagEvent(tag,event);
                    }
                } catch (Exception ex) {
                    LOG.warn("Can not create tag event:" + XmlTools.node2String(elem));
                    LOG.warn(ExceptionUtils.getStackTrace(ex));
                }
            }
        }
    }
}
